105. シーンの構築: 3.動きの追加

ユニフォーム変数を使用して、シェーダーにアニメーションを追加する方法を学びます。

p5.js 2.0 WebGL p5.strands Shader GLSL
Learning Tutorial

パーティクルに動きを加える

パーティクルをアニメーションさせるために、ユニフォーム変数 (Uniform variables) という概念を導入します。

ユニフォームは、JavaScript からシェーダーに渡される値です。グローバル変数のようなものだと考えてください。その値を変更すると、スケッチをリフレッシュすることなく、シェーダーのすべてのインスタンスが即座にその変更を認識します。これにより、ユニフォームはシェーダーのインタラクティブな部分に最適です。

const time = uniformFloat(() => millis());

p5.strands では、uniformFloatuniformVector3 などを使用してユニフォームを宣言します。これらはコールバック関数の中で宣言する必要がありますが、ストランド関数自体の内部ではありません。

オプションとして、ユニフォームに初期値(デフォルト値)を指定できます。デフォルト値を関数として設定すると、その関数は毎フレーム実行され、ユニフォームの値が更新されます。あるいは、p5.js の通常のシェーダーと同様に、myShader.setUniform('time', millis()) を呼び出して値を設定することも可能です。

スケッチのソースコードを見てみましょう:

let instancingShader;
let instancingStrokeShader;
let particleModel;

function instancingCallback() {
  // ユニフォーム変数の宣言を追加
  const time = uniformFloat(() => millis());

  // 擬似乱数関数
  function rand(seed) {
    return fract(sin(dot(seed, [12.9898, 78.233])) * 43758.5453123);
  }

  function getAnimatedSpherePosition() {
    let id = instanceID();
    let theta = rand([id, 0.1234]) * TWO_PI;
    // 時間の経過とともにパーティクルの位置を変化させます
    let phi = rand([id, 3.321]) * PI + time / 10000;

    // より興味深い形を作るために半径を変化させます
    let r = 200 * sin(phi);
    let x = r * sin(phi) * cos(theta);
    // Y 軸方向を少し引き伸ばします
    let y = r * 1.5 * cos(phi);
    let z = r * sin(phi) * sin(theta);
    return [x, y, z];
  }

  getWorldInputs((inputs) => {
    inputs.position += getAnimatedSpherePosition();
    return inputs;
  });
}

async function setup() {
  createCanvas(400, 400, WEBGL);
  pixelDensity(1);
  particleModel = buildGeometry(() => sphere(10, 4, 2));
  instancingShader = baseColorShader().modify(instancingCallback);
  instancingStrokeShader = baseStrokeShader().modify(instancingCallback);
}

function draw() {
  background(0);
  orbitControl();
  shader(instancingShader);
  fill(255, 100, 150);
  strokeShader(instancingStrokeShader);
  model(particleModel, 1000);
}

phi 角に time / 10000 を加え、さらに半径を sin() で変化させることで、脈動しながら引き伸ばされた球体の周りを移動するアニメーションを作成しています。

TIP
実験してみよう! sin()tan()acosh()、あるいはそれらの組み合わせに置き換えてみてください。シェーダーコードのわずかな変更が、劇的に異なる視覚効果を生み出すことがよくあります。

ユニフォームとして利用可能な p5.js 変数

p5.strands を使用すると、p5.js のよく知られたグローバル変数のいくつかが、最初からユニフォームとして利用可能です。

コールバック関数内では、以下のいずれかを直接使用できます:

  • 寸法 (Dimensions): width, height, displayWidth, displayHeight, windowWidth, windowHeight
  • 時間とフレーム (Time and frameCount): deltaTime, frameCount
  • ポインタ (Pointer): mouseIsPressed, mouseX, mouseY, pmouseX, pmouseY, pwinMouseX, pwinMouseY, winMouseX, winMouseY

これらは mouseIsPressed(boolean)を除いて、すべて浮動小数点数(float)です。

License

Original URL: https://beta.p5js.org/tutorials/intro-to-p5-strands/

License: MIT License

Copyright (c) 2015-present p5.js contributors & The Processing Foundation